package com.ys.chatserver.http.file.u;

import com.eva.framework.dbpool.DBDepend;
import com.eva.framework.dto.DataFromServer;
import com.eva.framework.httpfile.FileUpload;
import com.eva.framework.utils.LoggerFactory;
import com.google.gson.Gson;
import com.ys.chatserver.BaseConf;
import com.ys.chatserver.common.dto.cnst.EncodeConf;
import com.ys.chatserver.http.logic.LogicProcessor2;
import com.ys.chatserver.tool.ImgEqualScaleAndCutHelper;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;

/**
 * 群云盘图片上传
 *
 * @author Qxin
 */
public class CloudImageUploader extends HttpServlet {
    private static final long serialVersionUID = 1L;

    private static final int THRESHOLD_SIZE = 1024 * 200;// 200KB    //1024 * 1024 * 3; // 3MB
    private static final int MAX_FILE_SIZE = 1024 * 5000;//500;// 500KB     //1024 * 1024 * 40; // 40MB
    private static final int MAX_REQUEST_SIZE = MAX_FILE_SIZE;         //1024 * 1024 * 50; // 50MB

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doPost(request, response);
    }

    /**
     * handles file upload via HTTP POST method
     */
    protected void doPost(HttpServletRequest request,
                          HttpServletResponse response) throws ServletException, IOException {
        try {
            LoggerFactory.getLog().debug("[" + getDebugTAG() + "] 正在处理用户的文件上传请求 ...............");
            // 此方法目前是通用的文件上传处理API，默认是支持多文件上传的，目前是假定客户端只传一个文件，服务端其实并没有做检查，实际应用时不会！
            HashMap<String, Object> parametersFromClient = FileUpload.processFileUpload(request
                    , response
                    , getFileSaveDir()
                    , THRESHOLD_SIZE, MAX_FILE_SIZE, MAX_REQUEST_SIZE);

            // 文件上传处理成功
            if ((Boolean) parametersFromClient.get(FileUpload.SUCESS_KEY_NAME)) {
                DataFromServer objFromServer = new DataFromServer();
                objFromServer.setReturnValue("1");
                objFromServer.setSuccess(true);
                sendToClient(response, objFromServer);
                onUploadSucess(parametersFromClient);
            }
        } catch (Exception ex) {
            DataFromServer server = new DataFromServer();
            server.setReturnValue("0");
            server.setSuccess(false);
            sendToClient(response, server);
            onUploadFailure(ex);

        }
    }

    /**
     * 将数据对象发回给PC客户端.
     *
     * @param res           客户端响应HttpServletResponse对象
     * @param objFromServer 要发送的可系列化的数据对象
     */
    protected void sendToClient(HttpServletResponse res, DataFromServer objFromServer)
            throws IOException {
        String toCient = new Gson().toJson(objFromServer);
        // 发出的是JSON文本描述的DataFromClient对象
        byte[] bs = toCient.getBytes(EncodeConf.ENCODE_TO_CLIENT);//
        OutputStream out = res.getOutputStream();
        out.write(bs);
        out.flush();
        out.close();

    }

    protected void onUploadSucess(HashMap<String, Object> parametersFromClient) throws Exception {
        //群ID
        String groupId = (String) parametersFromClient.get("group_id");
        //上传者Id
        String userUid = (String) parametersFromClient.get("user_uid");
        // 文件名
        String fileName = (String) parametersFromClient.get("file_name");
        //文件md5
        String fileMd5 = (String) parametersFromClient.get("file_md5");

        LoggerFactory.getLog().debug("[" + getDebugTAG() + "] 用户" + userUid + "上传至群" + groupId + "的文件" + fileName
                + "数据上传成功，马上处理其它业务逻辑...");

        // 客户端传过来的数据（参数）的合法性检查
        if (groupId != null && userUid != null && fileName != null) {
            String uploadPath = getFileSaveDir();
            //已群ID作为文件夹，针对每个群创建对应的文件
            // 图片文件已经保存到的磁盘绝对路径
            File filePath = new File(String.format(uploadPath, groupId) + fileName);
            if (filePath.exists()) {
                // 生成原图的缩略图并存到磁盘
                File thumbnailFilePath = new File(String.format(uploadPath, groupId) + "th_" + fileName);
                // 如果文件名命名（存在，即意味着不需要写入磁盘了
                if (!thumbnailFilePath.exists()) {
                    ImgEqualScaleAndCutHelper.saveImageAsJpg(filePath.getAbsolutePath(), thumbnailFilePath.getAbsolutePath()
                            , 450, 450);
                }
            }
            if (!filePath.exists()) {
                LoggerFactory.getLog().error("[" + getDebugTAG() + "] 用户" + userUid + "的群云盘图片文件"
                        + fileName + "为何不存在？(绝对路径=" + filePath.getAbsolutePath() + ")");
            } else {
                afterTotalFileUploadComplete(fileName, filePath.length(), fileMd5, userUid, groupId);
            }

        } else {
            throw new Exception("[" + getDebugTAG() + "] 无效的参数：userUid=" + userUid + ", fileName=" + fileName + ".");
        }
    }

    protected void onUploadFailure(Exception ex) {
        LoggerFactory.getLog().error("[" + getDebugTAG() + "] 处理群云盘图片上传时出错了，" + ex.getMessage(), ex);
    }

    protected String getDebugTAG() {
        return "HTTP群云盘图片上传";
    }

    public static String getFileSaveDir() {
        return BaseConf.getInstance().getDIR_CLOUD_IMAGE_UPLOAD();
    }

    /**
     * 将最终合并完成的文件信息存库，以备使用文件时能快速高效地进行检索。
     *
     */
    private void afterTotalFileUploadComplete(String fileName
            , long file_size, String fileMd5, String user_id, String groupId) throws Exception {
        String fileMd5Lowsercase = fileMd5.toLowerCase();
        // 已经存在这条记录了
        if (!LogicProcessor2.db.queryData("select 1 from t_cloud where file_md5='"
                + fileMd5Lowsercase + "' and create_uid='"
                + user_id + "' and g_id='"
                + groupId + "' and file_type=2 and store_type = 0").isEmpty()) {
            LogicProcessor2.db.update("update t_cloud set file_name=?"
                            + ",file_size=?,update_time=" + DBDepend.getDefaultDatetimeFunc()
                            + ",g_id=?, create_uid=? where store_type = 0 and md5=?"
                    , new Object[]{fileName, file_size, groupId, user_id, fileMd5Lowsercase}, false);
        } else {
            LogicProcessor2.db.update(
                    "INSERT INTO t_cloud(file_name" +
                            ",file_size,file_md5,file_type,create_time,create_uid,g_id,store_type) " +
                            "VALUES(?,?,?,?, " + DBDepend.getDefaultDatetimeFunc() + ",?,?,?)"
                    , new Object[]{fileName, file_size, fileMd5, 2, user_id, groupId, 0}
                    , false);
        }
    }
}
